<?php
/**
 * 基础服务入口
 * User: minyifei.cn
 * Date: 15/7/8
 */

namespace MyfApi\Libs;


use Myf\Mvc\Log;
use MyfApi\Model\UserToken;

class BaseController extends \Controller{

    //token键名
    private $tokenKey = "xtoken";
    //签名键名
    private $signatureKey = "xsignature";
    //api加密秘钥
    private $secretKey = "myfapi*wooow";
    //访问时间戳
    private $timeKey = "xtime";

    //前置函数
    public function _before_action(){
        $white = $this->isWhite();
        if(!$white){
            //校验token
            $this->checkToken();
            //校验签名
            $this->checkSignature();
        }
    }

    /**
     * 成功输出结果
     * @param $data
     */
    public function echoSuccess($data){
        $uuid = session("myfapi_uuid");
        $res = array(
            "uuid"=>$uuid,
            "code"=>ErrorCode::SUCCESS,
            "result"=>$data,
        );
        Log::write(sprintf("uuid=%s,status=【success】,response=【%s】",$uuid,JSON($res)));
        $this->echoJson($res);
    }

    /**
     * 错误输出结果
     * @param $data
     * @param int $code
     */
    public function echoError($data,$code=ErrorCode::FAIL){
        $uuid = session("myfapi_uuid");
        $res = array(
            "uuid"=>$uuid,
            "code"=>$code,
            "error"=>$data,
        );
        Log::write(sprintf("uuid=%s,status=【fail】,response=【%s】",$uuid,JSON($res)));
        $this->echoJson($res);
    }

    /**
     * 生成token
     * @param int $userId
     * @return string
     */
    public function createToken($userId){
        createToken($userId);
    }

    /**
     * 获取当前登录用户的user_id
     * @return mixed
     * @throws \Exception
     */
    public function getUserId(){
        $token = getApiParam($this->tokenKey);
        $u = new UserToken();
        $ut = $u->findFirst("token",$token);
        if($ut){
            return $ut["user_id"];
        }else{
            ErrorCode::throwException(null,ErrorCode::TOKEN_ERROR);
        }
    }

    /**
     * 检查token
     * @return mixed|null
     * @throws \Exception
     */
    public function checkToken(){
        $token = getApiParam($this->tokenKey);
        $row = $this->parseToken($token);
        if(isset($row)){
            return $row;
        }else{
            ErrorCode::throwException(null,ErrorCode::TOKEN_ERROR);
        }
    }

    /**
     * 校验签名
     * 校验规则：首先需要把所有请求参数（除sigintrueKey外），进行key排序，然后把key和value用逗号链接，再把所有链接后的值用#号拼接成
     * 字符串，之后尾部拼上$secretKey，再取md5即可生成签名
     * @return bool
     * @throws \Exception
     */
    public function checkSignature(){
        //签名
        $signature = getApiParam($this->signatureKey);
        if(empty($signature)){
            ErrorCode::throwException(null,ErrorCode::SIGNATURE_ERROR);
        }
        //如果设置了测试签名，可以直接判断返回
        $c = C("signature");
        if($signature==$c){
            return true;
        }
        //时间戳
        $time = getApiParam($this->timeKey);
        //请求参数
        $req = $_REQUEST;
        unset($req["_url"]);
        unset($req[$this->signatureKey]);
        $req["xtime"]=$time;
        ksort($req);
        $strs = [];
        foreach($req as $k => $r){
            $strs[]=$k.",".$r;
        }
        $c = md5(sprintf("%s%s",join("#",$strs),$this->secretKey));
        if($c!=$signature){
            ErrorCode::throwException(null,ErrorCode::SIGNATURE_ERROR);
        }else{
            return true;
        }
    }

    /**
     * 解析token
     * @param $token
     * @return mixed|null
     */
    public function parseToken($token){
        return parseToken($token);
    }

    /**
     * 是否白名单
     * @return bool
     */
    private function isWhite(){
        $controller = getControllerName();
        $action = getActionName();
        $whiteUrls = C("white");
        if(!isset($whiteUrls)){
            $whiteUrls=array();
        }
        if(array_key_exists($controller,$whiteUrls) && in_array($action, $whiteUrls[$controller])){
            return true;
        }else{
            return false;
        }
    }

}